package com.rbac.configuration.secutity;


import com.rbac.configuration.secutity.filter.JwtAuthenticationFilter;
import com.rbac.configuration.secutity.ignore.CustomConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.ObjectUtils;


/**
 * @author zhangliang
 * @version 1.0  2.7版本以前 security配置
 * @date 2021/2/2 10:40
 */
//@Configuration
@Deprecated
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    protected Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    /**
     * 白名单配置
     */
    private final CustomConfig customConfig;

    private final AccessDeniedHandler accessDeniedHandler;

    private final UserDetailsService customUserDetailsService;



    public WebSecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter, CustomConfig customConfig, AccessDeniedHandler accessDeniedHandler, UserDetailsService customUserDetailsService) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
        this.customConfig = customConfig;
        this.accessDeniedHandler = accessDeniedHandler;
        this.customUserDetailsService = customUserDetailsService;
    }

    /**
     * 初始化  AuthenticationManager管理器
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 这里对登录的用户信息验证，需要传入用户服务信息
     *
     * @param auth 验证
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(encoder());
    }


    /**
     * 配置密码加密策略
     */
//    @Bean
    public BCryptPasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors()
//               关闭csrf
                .and().csrf().disable()
                // 登录行为由自己实现，参考 AuthController#login
                .formLogin().disable()
                .httpBasic().disable()
                //认证请求
                .authorizeRequests()
                //所有的请求都需要认证执行两次会报错，源码里面加了判断，开启动态验证url，就不要开启这个
//               .anyRequest()
//               .authenticated()
                .anyRequest()
                //rbac动态url认证，判断数据库是否存在此接口地址，没有返回权限不足
                .access("@RBACAuthorityService.hasPermission(request,authentication)")
                //登出行为自定义
                .and().logout().disable()
                //Session管理
                .sessionManagement()
                // 因为使用了JWT，所以这里不管理Session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //异常管理
                .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler);
        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) {
        WebSecurity and = web.ignoring().and();

        logger.info("web配置白名单");
        if (!ObjectUtils.isEmpty(customConfig.getIgnoreConfig())) {
            //  配置文件读取白名单
            customConfig.getIgnoreConfig().getGet().forEach(url ->
                    and.ignoring().antMatchers(HttpMethod.GET, url));

            // 忽略 POST
            customConfig.getIgnoreConfig().getPost().forEach(url -> and.ignoring().antMatchers(HttpMethod.POST, url));

            // 忽略 DELETE
            customConfig.getIgnoreConfig().getDelete().forEach(url -> and.ignoring().antMatchers(HttpMethod.DELETE, url));

            // 忽略 PUT
            customConfig.getIgnoreConfig().getPut().forEach(url -> and.ignoring().antMatchers(HttpMethod.PUT, url));

            // 忽略 HEAD
            customConfig.getIgnoreConfig().getHead().forEach(url -> and.ignoring().antMatchers(HttpMethod.HEAD, url));

            // 忽略 PATCH
            customConfig.getIgnoreConfig().getPatch().forEach(url -> and.ignoring().antMatchers(HttpMethod.PATCH, url));

            // 忽略 OPTIONS
            customConfig.getIgnoreConfig().getOptions().forEach(url -> and.ignoring().antMatchers(HttpMethod.OPTIONS, url));

            // 忽略 TRACE
            customConfig.getIgnoreConfig().getTrace().forEach(url -> and.ignoring().antMatchers(HttpMethod.TRACE, url));

            // 按照请求格式忽略
            customConfig.getIgnoreConfig().getPattern().forEach(url -> and.ignoring().antMatchers(url));

        }

    }
}
